package com.mxpio.erp.technology.controller;

import com.mxpio.erp.common.enums.OrderStatusEnums;
import com.mxpio.erp.common.technology.entity.BomInfo;
import com.mxpio.erp.common.technology.entity.BomInfoLine;
import com.mxpio.erp.common.technology.service.BomInfoLineService;
import com.mxpio.erp.common.technology.service.BomInfoService;
import com.mxpio.erp.common.technology.vo.BomTreeVO;
import com.mxpio.erp.common.technology.vo.ConsumptionVO;
import com.mxpio.erp.common.technology.vo.VersionVO;
import com.mxpioframework.common.vo.Result;
import com.mxpioframework.jpa.policy.CrudContext;
import com.mxpioframework.jpa.policy.impl.SmartCrudPolicyAdapter;
import com.mxpioframework.jpa.query.Criteria;
import com.mxpioframework.jpa.query.Operator;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.io.UnsupportedEncodingException;
import java.util.List;

@Tag(name = "BomInfoController", description = "Bom接口")
@RestController
@RequestMapping("/erp/tech/bom/")
public class BomInfoController {

    @Autowired
    private BomInfoService bomInfoService;

    @Autowired
    private BomInfoLineService bomInfoLineService;

    @PostMapping("listByItem/{itemCode}")
    @Operation(summary = "Bom列表", description = "获取Bom列表（无分页）", method = "POST")
    public Result<BomInfo> listByItem(@Parameter(description="父物料编号") @PathVariable(name = "itemCode", required = true) String itemCode,
                                            @Parameter(description="版本号") @RequestBody VersionVO vo ){
        BomInfo bomInfo = bomInfoService.listBom(itemCode,vo);
        return Result.OK(bomInfo);
    }

    @GetMapping("history/{itemCode}")
    @Operation(summary = "Bom历史列表", description = "获取Bom历史列表（无分页）", method = "GET")
    public Result<List<BomInfo>> history(@Parameter(description="父物料编号") @PathVariable(name = "itemCode", required = true) String itemCode){
        List<BomInfo> bomInfos = bomInfoService.listHistory(itemCode);
        return Result.OK(bomInfos);
    }

    @PostMapping("listSub")
    @Operation(summary = "查询Bom子级", description = "查询Bom子级", method = "POST")
    public Result<List<BomInfoLine>> listSub(@RequestBody BomTreeVO vo){
        List<BomInfoLine> bomInfoLines = bomInfoService.listSub(vo);
        return Result.OK(bomInfoLines);
    }

    @GetMapping("list")
    @Operation(summary = "Bom列表", description = "获取Bom列表（无分页）", method = "GET")
    public Result<List<BomInfo>> list(Criteria criteria) throws UnsupportedEncodingException {
        List<BomInfo> bomInfos = bomInfoService.list(BomInfo.class,criteria);
        return Result.OK(bomInfos);
    }
    @GetMapping("page")
    @Operation(summary = "Bom分页，以物料为基础展示", description = "获取Bom列表（分页）", method = "GET")
    public Result<Page<BomInfo>> page(Criteria criteria, Integer pageSize, Integer pageNo) throws UnsupportedEncodingException {
        Pageable page = PageRequest.of(pageNo-1, pageSize);
        return Result.OK(bomInfoService.page(page,criteria));
    }


    @GetMapping("list/{bomId}")
    @Operation(summary = "根据bomId获取Bom", description = "根据bomId获取Bom", method = "GET")
    public Result<BomInfo> getById(@PathVariable(name = "bomId", required = true) String bomId) {
        BomInfo bomInfo = bomInfoService.getById(BomInfo.class, bomId);
        return Result.OK(bomInfo);
    }

    @RequestMapping("save")
    @Operation(summary = "保存Bom", description = "保存Bom")
    public Result<BomInfo> save(@RequestBody BomInfo bomInfo) {
        bomInfoService.save(bomInfo,new SmartCrudPolicyAdapter(){
            @Override
            public boolean beforeInsert(CrudContext context) {
                Object o = context.getEntity();
                if(o instanceof BomInfoLine){
                    ((BomInfoLine) o).setBomId(bomInfo.getBomId());
                }
                return true;
            }
        });
        return Result.OK(bomInfo);
    }

    @DeleteMapping("remove/{bomIds}")
    @Operation(summary = "根据bomIds删除Bom", description = "删除Bom", method = "DELETE")
    @Transactional(readOnly = false)
    public Result<BomInfo> remove(@Parameter(description="bomId，多个id用英文逗号分隔") @PathVariable(name = "bomIds", required = true) String bomIds) {
        String[] bomId = bomIds.split(",");
        for(String key : bomId){
            Criteria c = Criteria.create().addCriterion("bomId", Operator.EQ, key);
            bomInfoLineService.removeBatch(BomInfoLine.class, c);
            bomInfoService.delete(BomInfo.class, key);
        }
        return Result.OK();
    }

    @PutMapping("submit/{bomId}")
    @Operation(summary = "提交Bom", description = "提交Bom", method = "PUT")
    public Result<BomInfo> submit(@Parameter(description="bomId") @PathVariable(name = "bomId", required = true) String bomId) {
        BomInfo bomInfo = bomInfoService.getById(BomInfo.class,bomId);
        if(bomInfo.getUseType().equals(OrderStatusEnums.BomStatus.CREATE.getStatusCode())){
            return bomInfoService.updateBomStatus(bomInfo, OrderStatusEnums.BomStatus.AUDITING);
        }else {
            return Result.error("非新增状态不可提交");
        }
    }

    @PutMapping("audit/{bomId}")
    @Operation(summary = "审核Bom", description = "审核Bom", method = "PUT")
    public Result<BomInfo> audit(@Parameter(description="bomId") @PathVariable(name = "bomId", required = true) String bomId) {
        BomInfo bomInfo = bomInfoService.getById(BomInfo.class,bomId);
        if(bomInfo.getUseType().equals(OrderStatusEnums.BomStatus.AUDITING.getStatusCode())){
            return bomInfoService.updateBomStatus(bomInfo, OrderStatusEnums.BomStatus.USING);
        }else {
            return Result.error("非审核中状态不可审核");
        }
    }

    @PutMapping("abandon/{bomId}")
    @Operation(summary = "弃审Bom", description = "弃审Bom", method = "PUT")
    public Result<BomInfo> abandon(@Parameter(description="bomId") @PathVariable(name = "bomId", required = true) String bomId) {
        BomInfo bomInfo = bomInfoService.getById(BomInfo.class,bomId);
        if(bomInfo.getUseType().equals(OrderStatusEnums.BomStatus.AUDITING.getStatusCode())){
            return bomInfoService.updateBomStatus(bomInfo, OrderStatusEnums.BomStatus.CREATE);
        }else{
            return Result.error("非审核中状态不可审核");
        }
    }

    @PutMapping("expired/{bomId}")
    @Operation(summary = "失效Bom", description = "失效Bom", method = "PUT")
    public Result<BomInfo> expired(@Parameter(description="bomId") @PathVariable(name = "bomId", required = true) String bomId) {
        BomInfo bomInfo = bomInfoService.getById(BomInfo.class,bomId);
        return bomInfoService.updateBomStatus(bomInfo, OrderStatusEnums.BomStatus.EXPIRED);
    }
    @PutMapping("voided/{bomId}")
    @Operation(summary = "作废Bom", description = "作废Bom", method = "PUT")
    public Result<BomInfo> voided(@Parameter(description="bomId") @PathVariable(name = "bomId", required = true) String bomId) {
        BomInfo bomInfo = bomInfoService.getById(BomInfo.class,bomId);
        return bomInfoService.updateBomStatus(bomInfo, OrderStatusEnums.BomStatus.CREATE);
    }

    @PostMapping("consumption")
    @Operation(summary = "材料定额领取计算", description = "材料定额领取计算", method = "POST")
    public Result<String> consumption(@RequestBody ConsumptionVO vo) {
        ImmutablePair<String,String> pair = bomInfoService.consumption(vo);
        if(StringUtils.isBlank(pair.getRight())){
            return Result.OK(pair.getLeft());
        }
        return Result.error(pair.getRight());
    }

    @GetMapping("calcAll")
    @Operation(summary = "计算所有bomline的消耗量，需要进行计算的bomline消耗量初始化为小于0", description = "计算所有bomline的消耗量", method = "GET")
    public Result<List<BomInfoLine>> calcAll() {
        bomInfoService.clacAll();
        return Result.OK();
    }
}
